﻿#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace VRChatAvatarToolkit {
    public class MoyuToolkitUtils : EditorWindow {
        public static void Print(params object[] strs)
        {
            string log = "";
            foreach (var str in strs)
            {
                if (log.Length > 0)
                {
                    log += " ";
                }
                log += str ?? "null";
            }
            Debug.Log(log);
        }

        private static MethodInfo clearMethod;
        public static void ClearConsole()
        {
            if (clearMethod == null)
            {
                Type log = typeof(EditorWindow).Assembly.GetType("UnityEditor.LogEntries");
                clearMethod = log.GetMethod("Clear");
            }
            clearMethod.Invoke(null, null);
        }

        public static string GetScriptPath()
        {
            var path = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(CreateInstance<MoyuToolkit>()));
            path = path.Substring(0, path.LastIndexOf("/") + 1);
            return path;
        }
        public static void LookGameObject(GameObject gameObject)
        {
            var view = SceneView.lastActiveSceneView;
            view.rotation = Quaternion.Euler(new Vector3(20, 180, 0));
            view.Repaint();

            Selection.activeGameObject = gameObject;
            SceneView.lastActiveSceneView.FrameSelected();
        }

        public static void WriteTxt(string str, string path)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            else
            {
                path = path.Replace("\\", "/");
                var dir = path.Substring(0, path.LastIndexOf("/"));
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
            }
            var file = File.CreateText(path);
            file.Write(str);
            file.Close();
        }
        public static string ReadTxt(string path)
        {
            if (File.Exists(path))
            {
                return File.ReadAllText(path);
            }
            return null;
        }


        public enum AvatarType {
            FBX = 0,
            SDK2 = 1,
            SDK3 = 2,
            Unknown = 3,
            Null = 4
        }
        public static AvatarType GetAvatarType(GameObject avatar)
        {
            if (avatar == null)
            {
                return AvatarType.Null;
            }
            else if (avatar.GetComponent<VRCSDK2.VRC_AvatarDescriptor>() != null)
            {
                return AvatarType.SDK2;
            }
            else if (avatar.GetComponent<VRC.SDK3.Avatars.Components.VRCAvatarDescriptor>() != null)
            {
                return AvatarType.SDK3;
            }
            else if (GetGameObjectForName(avatar, new string[] { "LeftEye", "RightEye", "Body" }).Keys.Count == 3)
            {
                return AvatarType.FBX;
            }
            return AvatarType.Unknown;
        }
        private static Dictionary<string, Transform> gameObjectDictionary;
        public static Dictionary<string, Transform> GetGameObjectForName(GameObject gameObject, string[] names)
        {
            gameObjectDictionary = new Dictionary<string, Transform>();

            var keys = new List<string>();
            keys.AddRange(names);

            FindGameObjectForName(gameObject.transform, keys);
            return gameObjectDictionary;
        }
        private static void FindGameObjectForName(Transform transform, List<string> name)
        {
            foreach (Transform child in transform)
            {
                if (name.Contains(child.name))
                {
                    gameObjectDictionary.Add(child.name, child);
                }
                else
                {
                    FindGameObjectForName(child, name);
                }
            }
        }

        public static List<GameObject> LinkGameObjectList(List<GameObject> list1, List<GameObject> list2)
        {
            List<GameObject> newList = new List<GameObject>();
            foreach (var obj in list1)
                if (obj != null && !newList.Contains(obj))
                    newList.Add(obj);
            foreach (var obj in list2)
                if (obj != null && !newList.Contains(obj))
                    newList.Add(obj);
            return newList;
        }
        public static string CreateRandomCode(int len)
        {
            string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            char[] chars = str.ToCharArray();
            StringBuilder strRan = new StringBuilder();
            System.Random ran = new System.Random();
            for (int i = 0; i < len; i++)
            {
                strRan.Append(chars[ran.Next(0, 36)]);
            }
            return strRan.ToString();
        }
        public static string CreateAvatarId(GameObject avatar)
        {
            var id = GetAvatarId(avatar);
            if (id != null)
                return id;
            id = "avatar_" + CreateRandomCode(36);
            //排重
            while (HasTag(id))
                id = "avatar_" + CreateRandomCode(36);
            //添加Tag
            AddTag(id, avatar);
            return id.Substring(7);
        }
        public static string GetAvatarId(GameObject avatar)
        {
            if (avatar == null)
                return null;
            var tag = avatar.tag;
            if (!tag.StartsWith("avatar_") || tag.Length != 43)
                return null;
            return tag.Substring(7);
        }

        private static void AddTag(string tag, GameObject obj)
        {
            if (!HasTag(tag))
            {
                SerializedObject tagManager = new SerializedObject(obj);//序列化物体
                SerializedProperty it = tagManager.GetIterator();//序列化属性
                while (it.NextVisible(true))//下一属性的可见性
                {
                    if (it.name == "m_TagString")
                    {
                        it.stringValue = tag;
                        tagManager.ApplyModifiedProperties();
                    }
                }
            }
        }
        private static bool HasTag(string tag)
        {
            for (int i = 0; i < UnityEditorInternal.InternalEditorUtility.tags.Length; i++)
            {
                if (UnityEditorInternal.InternalEditorUtility.tags[i].Contains(tag))
                    return true;
            }
            return false;
        }
    }
}
#endif